package top.hekun.study.core;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import top.hekun.study.core.util.ClassFileUtil;


import java.io.File;

import java.io.IOException;

import static org.objectweb.asm.Opcodes.*;


/**
 * 〈ClassWriter 类实例〉
 * 生成一个接口
 *
 * @author: Sakura
 * @date: 2023/4/25
 */
public class ClassWriterGenerationToInterface {

    public static void main(String[] args) throws IOException {
        File classFile = getClassFile();
        ClassWriter classWriter = getClassWriter();
        generateClassInfo(classWriter);
        generateClassFieldInfo(classWriter);
        generateClassMethodInfo(classWriter);
        byte[] classFileCore = getClassFileCore(classWriter);
        writeClassFileCore(classFileCore,classFile);
    }

    /**
     *  生成接口类信息
     * @param classWriter
     */
    private static void generateClassInfo(ClassWriter classWriter)  {


        /**
         *   Opcodes.V1_8, // jdk 版本
         *  Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,  // 类表示 使用+ 和| 运算 都可以 , 此处定义了 公有的抽象类接口
         *  "top/hekun/study/three/HelloWord",  // 类名称
         *  null,   // 泛型
         *  "java/lang/Object", 父类
         *   new String[]{"a/b/c/d0","a/b/c/d1"}  继承的接口
         */
        classWriter.visit(
                Opcodes.V1_8,
                ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
                "top/hekun/study/classFileModel/HelloWordInterface",
                null,
                "java/lang/Object",
                new String[]{"a/b/c/d0", "a/b/c/d1"}
        );


    }

    /**
     * 生成字段信息
     * access–字段的访问标志（请参阅操作代码）。此参数还指示字段是合成的和/或不推荐使用的。
     * name–字段的名称。
     * descriptor–字段的描述符（请参见类型）。
     * 签名–字段的签名。如果字段的类型不使用泛型类型，则可能为null。
     * value–字段的初始值。如果字段没有初始值，则此参数可能为null，
     * 它必须是Integer、Float、Long、Double或String（分别用于int、Float、Long或String字段）
     * 此参数仅用于静态字段。对于非静态字段，它的值将被忽略，
     * 这些字段必须通过构造函数或方法中的字节码指令进行初始化。
     * @param classWriter
     */
    private static void generateClassFieldInfo(ClassWriter classWriter){
        FieldVisitor fieldVisitor0 = classWriter.visitField(
                ACC_PUBLIC|ACC_FINAL|ACC_STATIC,
                "age",
                "I",
                null,
                22
        );
        fieldVisitor0.visitEnd();
        FieldVisitor fieldVisitor1 = classWriter.visitField(
                ACC_PUBLIC|ACC_FINAL|ACC_STATIC,
                "name",
                "Ljava/lang/String;",
                null,
                "坤坤"
        );
        fieldVisitor1.visitEnd();
    }

    /**
     * 生成方好
     * @param classWriter
     */
    private static void generateClassMethodInfo(ClassWriter classWriter){
        MethodVisitor methodVisitor = classWriter.visitMethod(
                ACC_PUBLIC|ACC_ABSTRACT,
                "setName",
                "(Ljava/lang/String;IJ)V",
                null,
                null
        );
        methodVisitor.visitEnd();
    }
    /**
     *
     * 获取类文件
     * @return
     */
    private static File getClassFile() {
        String className = "HelloWordInterface";
        File file = new File(ClassFileUtil.getClassFileModelPath(), className + ".class");
        return file;
    }

    /**
     * 获取 ClassWriter 对象
     * @return
     */
    private static ClassWriter getClassWriter() {
        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        return classWriter;
    }

    /**
     * 获取类的字节码
     * 注: 本方法会自动调用visitEnd()
     * @param classWriter
     * @return
     */
    private static byte[] getClassFileCore(ClassWriter classWriter) {
        classWriter.visitEnd();
        byte[] core = classWriter.toByteArray();
        return core;

    }

    /**
     * 文件写入数据
     * @param core
     * @param classFilePath
     */
    private static void writeClassFileCore(byte[] core, File classFilePath) {
        ClassFileUtil.classFileCoreWrite(core, classFilePath);
    }


}
